use Modern::Perl;
use GD;
use GD::Text;
use GD::Graph::mixed;
use GD::Graph::Data;
use Getopt::Long;
use IO::All;
use List::Util qw(max min);

my $file;
GetOptions(
  "file|f=s" => \$file,
  "help|?"  => \&usage,
);

&usage unless $file and -f $file;


# Some default value

my $graph_type = "png";
my $x_extend = 500;
my ($width, $height) = (1200, 300);
my $output = $file.".".$graph_type;

# Read and parse data which plot needs
my @content = io->file($file)->slurp;
map{ chomp $_; } @content;

# original data
my @x = split /\s+/, $content[0];
my $log2 = NA2undef([ split /\s+/, $content[1] ]);
my $log2_smoothed = NA2undef([ split /\s+/, $content[2] ]);
my $is_sexual = $content[7];
my $na_region = h_annotate(\@x, [sort{$a<=>$b}split /\s+/, $content[5]], $is_sexual);
my $data_base_isna_regions = h_annotate(\@x, [sort{$a<=>$b}split /\s+/, $content[6]], $is_sexual);
my $centromere = h_annotate(\@x, [split /\s+/, $content[8]], $is_sexual);
my $reported_upper = [split /\s+/, $content[10]];
my $reported_lower = [split /\s+/, $content[11]];
my $zct = NA2undef([ split /\s+/, $content[3] ]);
my $z_smoothed = NA2undef([ split /\s+/, $content[4] ]);

# 打印这2个结果
#map{print $_,"\t"}@x;
#print "\n";
#map{print defined($_)?$_:"NA","\t";}@{$na_region};
#print "\n";
#map{print defined($_)?$_:"NA","\t";}@{$data_base_isna_regions};
#print "\n";


# X position
push @x, ((scalar(@x) + 1)..(scalar(@x) + $x_extend));
unshift @x, (-$x_extend..0);

# log2
push @{$log2}, (undef)x$x_extend;
unshift @{$log2}, (undef)x($x_extend + 1);
push @{$log2_smoothed},(undef)x$x_extend;
unshift @{$log2_smoothed},(undef)x($x_extend + 1);


# na_region
push @{$na_region},(undef)x$x_extend;
unshift @{$na_region},(undef)x($x_extend + 1);

# data_base_isna_regions
push @{$data_base_isna_regions},(undef)x$x_extend;
unshift @{$data_base_isna_regions},(undef)x($x_extend + 1);

# centromere
push @{$centromere},(undef)x$x_extend;
unshift @{$centromere},(undef)x($x_extend + 1);

# Z score
push @{$zct}, (undef)x$x_extend;
unshift @{$zct}, (undef)x($x_extend + 1);
push @{$z_smoothed}, (undef)x$x_extend;
unshift @{$z_smoothed}, (undef)x($x_extend + 1);
scalar_y($zct);
scalar_y($z_smoothed);

# Report regions
unless ($reported_upper->[0] =~ /FALSE/){
  $reported_upper = [map{$_ + $x_extend + 1;}@{$reported_upper}];
}
unless ($reported_lower->[0] =~ /FALSE/){
  $reported_lower = [map{$_ + $x_extend + 1;}@{$reported_lower}];
}

# Generate plot data
my $x_length = scalar(@x);
my @log2min = (log2(1/2))x$x_length;
my @log2max = (log2(3/2))x$x_length;
my @zmin = (-3)x$x_length;
my @zmax = (3)x$x_length;
for my $index (0..$#log2min){
  if ($index%199 > 100){
    $log2min[$index] = undef;
    $log2max[$index] = undef;
    $zmin[$index] = undef;
    $zmax[$index] = undef;
  }
}

my @data_log2 = (
  \@x,
  $log2,
  [(0)x$x_length],
  \@log2min,
  \@log2max,
  $log2_smoothed,
  $na_region,
  $data_base_isna_regions,
  $centromere,
);

my @data_z = (
  \@x,
  $zct,
  [(0)x$x_length],
  \@zmin,
  \@zmax,
  $z_smoothed,
  $na_region,
  $data_base_isna_regions,
  $centromere,
);

# Produce GD::Graph::mixed
my $graph_log2 = new GD::Graph::mixed($width, $height);
my $graph_z = new GD::Graph::mixed($width, $height);

$graph_log2->set(
  y_label => 'log2 ratio',
  title => "Chr 1",
  l_margin => 20,
  r_margin => 20,
  b_margin => 20,
  types => [qw(points lines lines lines lines lines lines lines)],
  y_max_value => 3,
  y_min_value => -3,
  x_max_value => $x[-1],
  x_min_value => -$x_extend,
  y_tick_number => 6,
  y_tick_length => -10,
  x_tick_number => int(scalar(@x)/2000),
  x_tick_offset => 1,
  x_label_skip => 10000,
  x_tick_length => -5,
  x_number_format => \&x_format,
  y_number_format => \&y_format,
  axis_space => 20,
  text_space => 10,
  x_plot_values => 1,
  y_plot_values => 1,
  dclrs => [qw(gray black black black blue red cyan black)],
  line_width => 2,
  line_types => [undef, 1, 1, 1, 1, 1, 1, 1],
  skip_undef => 1,
  marker_size => 1,
  transparent => 0,
);

my $font = GD::Text->new() or die GD::Text::error();
$font->set_text("Hello");
$font->set(ptsize=>50);
$graph_z->set(
  y_label => 'z value',
  x_label => 'Blocks(20000*1)',
  x_label_position => 0.5,
  t_margin => 20,
  l_margin => 20,
  r_margin => 20,
  b_margin => 20,
  types => [qw(lines lines lines lines lines lines lines lines)],
  y_max_value => 10,
  y_min_value => -10,
  x_max_value => $x[-1],
  x_min_value => -$x_extend,
  y_tick_number => 4,
  y_tick_length => -10,
  x_tick_number => int(scalar(@x)/2000),
  x_tick_offset => 1,
  x_label_skip => 1,
  x_tick_length => -5,
  x_number_format => \&x_format,
  y_number_format => \&y_format,
  axis_space => 20,
  text_space => 10,
  x_plot_values => 1,
  y_plot_values => 1,
  dclrs => [qw(gray black black black blue red cyan black)],
  line_width => 2,
  line_types => [undef, 1, 1, 1, 1, 1, 1, 1],
  skip_undef => 1,
  transparent => 0,
);

$graph_log2->set_title_font('Dustismo_Sans.ttf',60);
$graph_log2->set_y_label_font('Dustismo_Sans.ttf',30);
$graph_log2->set_x_axis_font(GD::Font->Large);
$graph_log2->set_y_axis_font(GD::Font->Large);
my $gd_log2 = $graph_log2->plot(\@data_log2) or die $graph_log2->error;

$graph_z->set_y_label_font('Dustismo_Sans.ttf',30);
$graph_z->set_x_label_font('Dustismo_Sans.ttf',30);
$graph_z->set_x_axis_font(GD::Font->Large);
$graph_z->set_y_axis_font(GD::Font->Large);
my $gd_z = $graph_z->plot(\@data_z) or die $graph_z->error;

# Report region plot
#=pod
unless ($reported_lower->[0] =~ /FALSE/) {
  my $mclr = $graph_log2->{graph}->colorAllocate(255,0,0);
  my $mclr_z = $graph_z->{graph}->colorAllocate(255,0,0);
  for my $position (@{$reported_lower}) {
    v_lines($graph_log2, $position, $mclr);
    v_lines($graph_z, $position, $mclr_z);
  }
}
unless ($reported_upper->[0] =~ /FALSE/){
  my $mclr = $graph_log2->{graph}->colorAllocate(78,238,148);
  my $mclr_z = $graph_z->{graph}->colorAllocate(78,238,148);
  for my $position (@{$reported_upper}) {
    v_lines($graph_log2, $position, $mclr);
    v_lines($graph_z, $position, $mclr_z);
  }
}
#=cut
# Merge image
my ($log2x, $log2y) = $gd_log2->getBounds();
my ($zx, $zy) = $gd_z->getBounds();
my ($outx, $outy) = ($log2x>$zx?$log2x:$zx, $log2y + $zy);
my $gd_out = GD::Image->new($outx,$outy,1);
$gd_out->copy($gd_log2,0,0,0,0,$log2x,$log2y);
$gd_out->copy($gd_z,0,$log2y,0,0,$zx,$zy);

open (IMGA, '>',$output) or die $!;
binmode IMGA;
print IMGA $gd_out->$graph_type;


###############################
#Some function
###############################

sub x_format {
  my $value = shift;
  int($value);
}

sub y_format {
  my $value = shift;
  sprintf("%.1f",$value);
}

sub log2 {
  my $n = shift;
  log($n)/log(2);
}

sub NA2undef {
  my $array = shift;
  [map{
    $_
      ? $_ =~ /NA/
        ? undef
        : $_
      : undef;
      
  } @{$array}];
}

sub h_annotate{
  # $x: all x values
  # $position: an array ref
  # $value: y-value
  my ($x,$position,$value) = @_;
  my $x_length = scalar(@{$x});
  my $ret = [(undef)x$x_length];
  my $start_position = undef;
  for my $index (0..$#{$position}) {
    if ($index%2 == 0) {
      $start_position = $position->[$index];
    } else {
      my $end_position = $position->[$index];
      my @len = ($start_position..$end_position);
      if (scalar(@len)>7) {
        map {
          $ret->[$_-1] = $value;
        }@len;
      }
    }
  }
  $ret;
}

sub v_lines{
  my ($graph,$position,$mclr) = @_;
  my $x_zero = $graph->{left};
  my $x_step = $graph->{x_step};
  my $t = $graph->{top};
  my $b = $graph->{bottom};
  my $xp = $x_zero + $x_step*$position;
  #note "^^^^^^";
  #note $position;
  #note "######";
  $graph->{graph}->dashedLine($xp, $t, $xp, $b, $mclr);
}

sub scalar_y{
  my $data = shift;
  map{
    my $index = $_;
    if (defined $data->[$index] and abs($data->[$index])>10) {
      $data->[$index] = undef;
    }
  } (0..$#{$data});

}

sub usage {
  my $USAGE = <<"USAGE";;
Description:
Version:
Example:        $0 -f <plot file>
Usage:
    --file|-f       : Plot file which generate by BerryCNV program. In general, the file name is *.Chr*.plot.txt
    --help          : Print help
USAGE
  print $USAGE;
  exit;
}
